package com.xbongbong.paas.service.workflow.setting.impl;

import com.alibaba.fastjson.JSON;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.config.enums.WorkflowTriggerMethodEnum;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.ProFormHelp;
import com.xbongbong.paas.pojo.workflow.NodeCoreConfigurationPojo;
import com.xbongbong.paas.pojo.workflow.WorkflowNodeTreePojo;
import com.xbongbong.paas.pojo.workflow.nodes.vo.ObtainSingleDataNodeVO;
import com.xbongbong.paas.pojo.workflow.nodes.vo.WorkflowNodeGetVO;
import com.xbongbong.paas.pojo.workflow.settings.WorkflowGetPojo;
import com.xbongbong.paas.pojo.workflow.settings.vo.FilterConditionVO;
import com.xbongbong.paas.pojo.workflow.settings.vo.WorkflowEnableVO;
import com.xbongbong.paas.service.workflow.setting.AbstractWorkflowNodeSettings;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.util.WorkflowNodeUtil;
import com.xbongbong.pro.enums.ErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.ProErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.workflow.domain.entity.WorkflowNodeEntity;
import com.xbongbong.workflow.domain.entity.ext.WorkflowNodeEntityExt;
import com.xbongbong.workflow.enums.WorkflowNodeTypeEnum;
import com.xbongbong.workflow.pojo.nodes.ObtainSingleDataNode;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * @author 吴峰
 * @date 2021/05/21 14:35
 */
@Service("workflowNodeSingleDataSettings")
public class WorkflowNodeSingleDataSettings extends AbstractWorkflowNodeSettings {

    private static String CONSTANT = "constant.workflowNode.single_data_node_content";

    private static final Logger LOGGER = LoggerFactory.getLogger(WorkflowNodeSingleDataSettings.class);
    @Resource
    private ProFormHelp proFormHelp;

    @Override
    public Integer type() {
        return WorkflowNodeTypeEnum.SINGLE_DATA_NODE.getType();
    }

    @Override
    public WorkflowNodeTreePojo getContent(WorkflowNodeEntity workflowNodeEntity, WorkflowGetPojo workflowGetPojo) throws XbbException {
        WorkflowNodeTreePojo workflowNodeTreePojo = new WorkflowNodeTreePojo();
        try {
            List<String> list = getNodeContent(workflowGetPojo, workflowNodeEntity, CONSTANT);
            workflowNodeTreePojo.setContent(list);
        } catch (Exception e) {
            LOGGER.error("WorkflowNodeSingleDataSettings.getContent error", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return workflowNodeTreePojo;
    }

    @Override
    public WorkflowNodeGetVO get(WorkflowNodeEntity workflowNodeEntity) throws XbbException {
        try {
            ObtainSingleDataNode obtainSingleDataNode = JSON.parseObject(workflowNodeEntity.getConfigData(), ObtainSingleDataNode.class);
            NodeCoreConfigurationPojo nodeCoreConfigurationPojo = new NodeCoreConfigurationPojo();

            ObtainSingleDataNodeVO obtainSingleDataNodeVO = getObtainMultiDataNodeVo(workflowNodeEntity, obtainSingleDataNode);

            nodeCoreConfigurationPojo.setObtainSingleDataNode(obtainSingleDataNodeVO);
            // 获取表单名称
            String formName = getFormName(workflowNodeEntity, workflowNodeEntity.getCorpid());
            return new WorkflowNodeGetVO(formName, workflowNodeEntity.getAppId(), workflowNodeEntity.getFormId(), workflowNodeEntity.getMenuId(), workflowNodeEntity.getSaasMark(), workflowNodeEntity.getBusinessType(),
                    workflowNodeEntity.getUid(), workflowNodeEntity.getId(), workflowNodeEntity.getPrevId(), workflowNodeEntity.getWrapperId(), nodeCoreConfigurationPojo);
        } catch (Exception e) {
            LOGGER.error("WorkflowNodeSingleDataSettings.get error", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    private ObtainSingleDataNodeVO getObtainMultiDataNodeVo(WorkflowNodeEntity workflowNodeEntity, ObtainSingleDataNode obtainSingleDataNode) throws XbbException {
        if (Objects.isNull(obtainSingleDataNode) || obtainSingleDataNode.getFilterCondition() == null) {
            return null;
        }
        Set<Long> workflowNodeIdSet = new HashSet<>();
        Set<Long> formIdSet = new HashSet<>();
        Set<Long> workOrderFormIdSet = new HashSet<>();
        String corpid = workflowNodeEntity.getCorpid();
        if (Objects.equals(XbbRefTypeEnum.WORK_ORDER.getCode(), workflowNodeEntity.getBusinessType())) {
            workOrderFormIdSet.add(workflowNodeEntity.getFormId());
        } else {
            formIdSet.add(workflowNodeEntity.getFormId());
        }
        conditionGetFormIdSet(obtainSingleDataNode.getFilterCondition(), formIdSet, workOrderFormIdSet, workflowNodeIdSet);
        Map<Long, Map<String, FieldAttrEntity>> workOrderExplainMap = proFormHelp.getWorkOrderFormFieldMap(workOrderFormIdSet, corpid);
        Map<Long, Map<String, FieldAttrEntity>> explainMap = proFormHelp.getFormFieldMap(formIdSet, corpid);
        Map<Long, WorkflowNodeEntity> workflowNodeMap = getWorkflowNodeMap(workflowNodeIdSet, corpid);

        List<FilterConditionVO> condition = getReturnConditionList(obtainSingleDataNode.getFilterCondition(), workflowNodeEntity.getFormId(), workflowNodeEntity.getBusinessType(), explainMap, workOrderExplainMap, workflowNodeMap);
        String orderFieldName = getOrderFieldName(workflowNodeEntity, workOrderExplainMap, explainMap, obtainSingleDataNode.getOrderField());
        ObtainSingleDataNodeVO obtainMultiDataNodeVO = new ObtainSingleDataNodeVO(obtainSingleDataNode.getEditedData(), obtainSingleDataNode.getDataSources(), condition, obtainSingleDataNode.getOrderField(), orderFieldName,
                obtainSingleDataNode.getOrder(), obtainSingleDataNode.getNoDataEvent()
        );
        return obtainMultiDataNodeVO;
    }

    @Override
    public WorkflowEnableVO check(WorkflowNodeEntity workflowNodeEntity, Map<Long, WorkflowNodeEntity> nodeMap, WorkflowGetPojo workflowGetPojo) throws XbbException {
        WorkflowEnableVO workflowEnableVO = new WorkflowEnableVO();
        ObtainSingleDataNode obtainSingleDataNode = JSON.parseObject(workflowNodeEntity.getConfigData(), ObtainSingleDataNode.class);
        try {
            if (Objects.equals(workflowNodeEntity.getTriggerType(), WorkflowTriggerMethodEnum.FORM.getType())) {
                if (Objects.isNull(workflowNodeEntity.getFormId()) || Objects.equals(0L, workflowNodeEntity.getFormId())) {
                    // 表单不一致
                    return new WorkflowEnableVO(0, workflowNodeEntity.getId(), I18nMessageUtil.getMessage(MessageConstant.FORM_NOT_EXIST));
                }
                WorkflowNodeEntity node = nodeMap.get(workflowNodeEntity.getId());
                if (!equals(workflowNodeEntity.getFormId(), workflowNodeEntity.getBusinessType(), node.getFormId(), node.getBusinessType())) {
                    // 表单不一致
                    return new WorkflowEnableVO(0, workflowNodeEntity.getId(), I18nMessageUtil.getMessage(ProErrorCodeEnum.API_ERROR_260042.getMsg()));
                }
                validateFilterCondition(workflowNodeEntity, obtainSingleDataNode.getFilterCondition(), workflowGetPojo);
            }
        } catch (XbbException e) {
            workflowEnableVO.setSuccess(0);
            workflowEnableVO.setMessage(e.getMsg());
        }

        return workflowEnableVO;
    }

    @Override
    public void replaceWorkflowNodeId(WorkflowNodeEntityExt workflowNodeEntityExt, Map<Long, Long> workflowNodeMap) throws XbbException {
        ObtainSingleDataNode obtainSingleDataNode = JSON.parseObject(workflowNodeEntityExt.getConfigData(), ObtainSingleDataNode.class);
        if (Objects.nonNull(obtainSingleDataNode) && CollectionUtils.isNotEmpty(obtainSingleDataNode.getFilterCondition())) {
            WorkflowNodeUtil.conditionReplaceNodeId(obtainSingleDataNode.getFilterCondition(), workflowNodeMap);
            workflowNodeEntityExt.setConfigData(JSON.toJSONString(obtainSingleDataNode));
        }
    }
}

